<script lang="ts" setup>
import type { MenuOption, MenuResp } from '#/api/system/menu/model';
import type { Role } from '#/api/system/role/model';

import { defineEmits, ref } from 'vue';

import { useVbenDrawer, useVbenForm } from '@vben/common-ui';

import { menuTreeList, roleMenuTreeSelect } from '#/api/system/menu';
import { addRole, getRoleDetail, modifyRole } from '#/api/system/role/role';

import { drawerSchema } from './config-data';

const emit = defineEmits<{ reload: [] }>();

// 定义侧拉里面的表单
const [Form, formApi] = useVbenForm({
  showDefaultActions: false,
  layout: 'horizontal',
  schema: drawerSchema(),
});
const defaultProps = {
  children: 'children',
  label: 'label',
};
// 定义是否是修改进来的标识
const isUpdateRef = ref<boolean>(false);
const menu = ref<MenuResp>({ checkedKeys: [], menus: [] });
const menuRoleRef = ref<Role>({ roleId: -1 });
// 定义侧拉容器
const [Drawer, drawerApi] = useVbenDrawer({
  // 打开角色侧拉监听
  async onOpenChange(isOpen: boolean) {
    if (!isOpen) {
      return;
    }
    try {
      drawerApi.drawerLoading(true);
      const { roleId, isUpdate } = drawerApi.getData();
      isUpdateRef.value = isUpdate;
      if (isUpdate) {
        // 获取对应角色的菜单和菜单权限
        menu.value = await roleMenuTreeSelect(roleId);
        // 获取角色详情
        const roleDetail = await getRoleDetail(roleId);
        menuRoleRef.value = roleDetail;
        // 设置表单回显
        await formApi.setValues(roleDetail);
        // 设置属性节点选中回显
        treeRef.value!.setCheckedKeys(menu.value.checkedKeys, false);
      } else {
        await formApi.resetForm();
        menu.value.menus = await menuTreeList();
      }
    } catch (error) {
      console.error(error);
    } finally {
      drawerApi.drawerLoading(false);
    }
  },
  async onClosed() {
    // 重置表单
    await formApi.resetForm();
  },
  // 确认提交角色
  async onConfirm() {
    try {
      drawerApi.drawerLoading(true);
      const { valid } = await formApi.validate();
      if (!valid) {
        return;
      }
      const data = await formApi.getValues<Role>();
      // 是否是否关联
      data.menuCheckStrictly = menuRoleRef.value.menuCheckStrictly;
      // 获取全选节点
      const checkedKeys = treeRef.value!.getCheckedKeys(false);
      // 获取半选节点
      const halfCheckKeys = treeRef.value!.getHalfCheckedKeys();
      // 组装
      checkedKeys.unshift(...halfCheckKeys);
      data.menuIds = checkedKeys;
      // 动态判断调用新增还是修改
      isUpdateRef.value ? await modifyRole(data) : await addRole(data);
      // 发射刷新列表
      emit('reload');
      drawerApi.close();
    } catch (error) {
      console.error(error);
    } finally {
      drawerApi.drawerLoading(false);
    }
  },
});
// 展开/收起
const treeRef = ref<InstanceType<typeof ElTree>>();
function isExpendTree(val: boolean) {
  const tree = treeRef.value;
  if (val) {
    if (tree) {
      const nodes = tree.store._getAllNodes(); // 获取所有节点
      nodes.forEach((node: any) => {
        node.expanded = true; // 设置展开状态
      });
    }
  } else {
    if (tree) {
      const nodes = tree.store._getAllNodes();
      nodes.forEach((node: any) => {
        node.expanded = false;
      });
    }
  }
}
// 递归收集所有节点 ID
const getAllKeys = (treeData: MenuOption[]) => {
  const keys: number[] = []; // 或 number[]，根据你的 node-key 类型
  for (const node of treeData) {
    keys.push(node.id);
    if (node.children) {
      keys.push(...getAllKeys(node.children));
    }
  }
  return keys;
};
// 全选/全不选
function isAllSelect(val: boolean) {
  const tree = treeRef.value;
  if (val) {
    const allKeys = getAllKeys(menu.value.menus);
    tree!.setCheckedKeys(allKeys, false);
  } else {
    tree!.setCheckedKeys([], false);
  }
}
// 是否子父关联
function isChildParent(val: boolean) {
  menuRoleRef.value.menuCheckStrictly = val;
}
</script>
<template>
  <Drawer :title="isUpdateRef ? '修改' : '新增'">
    <Form>
      <template #checkboxGroup>
        <el-checkbox label="展开/折叠" @change="isExpendTree" />
        <el-checkbox label="全选/全不选" @change="isAllSelect" />
        <el-checkbox
          v-model="menuRoleRef.menuCheckStrictly"
          checked
          label="父子联动"
          @change="isChildParent"
        />
      </template>
      <template #permTree>
        <ElTree
          class="w-screen rounded-lg border"
          ref="treeRef"
          :data="menu.menus"
          show-checkbox
          node-key="id"
          highlight-current
          :check-strictly="!menuRoleRef.menuCheckStrictly"
          :props="defaultProps"
        />
      </template>
    </Form>
  </Drawer>
</template>
<style scoped lang="scss">
:deep(.el-input-number) {
  width: 100%;
}
</style>
